﻿
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Classy pre ObservableCollection<T> pre SilverLight 5
// pozbieral som z webu :-)
// 
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 
//----------------------------------------------------------------------------
  //
  // <copyright file="NotifyCollectionChangedEventArgs.cs" company="Microsoft">
  //    Copyright (C) Microsoft Corporation.  All rights reserved.
  // </copyright>
  //
  // Description: NotifyCollectionChanged event arguments
  //
  // Specs:       [....]/connecteddata/Specs/INotifyCollectionChanged.mht
  //
  //---------------------------------------------------------------------------

  using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
  //using System.Windows;
  // using MS.Internal;                  // Invariant.Assert

namespace System.Collections.Specialized
{
  // Summary:
  //     Notifies listeners of dynamic changes, such as when items get added and removed
  //     or the whole list is refreshed.
  public interface INotifyCollectionChanged
  {
    // Summary:
    //     Occurs when the collection changes.
    event NotifyCollectionChangedEventHandler CollectionChanged;
  }
  /// <summary>
  /// This enum describes the action that caused a CollectionChanged event.
  /// </summary>
  public enum NotifyCollectionChangedAction
  {
    /// <summary> One or more items were added to the collection. </summary>
    Add,
    /// <summary> One or more items were removed from the collection. </summary>
    Remove,
    /// <summary> One or more items were replaced in the collection. </summary>
    Replace,
    /// <summary> One or more items were moved within the collection. </summary>
    Move,
    /// <summary> The contents of the collection changed dramatically. </summary>
    Reset,
  }

  /// <summary>
  /// Arguments for the CollectionChanged event.
  /// A collection that supports INotifyCollectionChangedThis raises this event
  /// whenever an item is added or removed, or when the contents of the collection
  /// changes dramatically.
  /// </summary>
  public class NotifyCollectionChangedEventArgs : EventArgs
  {
    //-----------------------------------------------------
    //
    //  Constructors
    //
    //-----------------------------------------------------

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a reset change.
    /// </summary>
    /// <param name="action">The action that caused the event (must be Reset).
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
    {
      if (action != NotifyCollectionChangedAction.Reset)
        throw new ArgumentException("(SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Reset)", "action");

      InitializeAdd(action, null, -1);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
    /// </summary>
    /// <param name="action">The action that caused the event; can only be Reset, Add or Remove action.
    /// <param name="changedItem">The item affected by the change.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem)
    {
      if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
              && (action != NotifyCollectionChangedAction.Reset))
        throw new ArgumentException("SR.Get(SRID.MustBeResetAddOrRemoveActionForCtor)", "action");

      if (action == NotifyCollectionChangedAction.Reset)
      {
        if (changedItem != null)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresNullItem)", "action");

        InitializeAdd(action, null, -1);
      }
      else
      {
        InitializeAddOrRemove(action, new object[] { changedItem }, -1);
      }
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a one-item change.
    /// </summary>
    /// <param name="action">The action that caused the event.
    /// <param name="changedItem">The item affected by the change.
    /// <param name="index">The index where the change occurred.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index)
    {
      if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
              && (action != NotifyCollectionChangedAction.Reset))
        throw new ArgumentException("SR.Get(SRID.MustBeResetAddOrRemoveActionForCtor)", "action");

      if (action == NotifyCollectionChangedAction.Reset)
      {
        if (changedItem != null)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresNullItem)", "action");
        if (index != -1)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresIndexMinus1)", "action");

        InitializeAdd(action, null, -1);
      }
      else
      {
        InitializeAddOrRemove(action, new object[] { changedItem }, index);
      }
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change.
    /// </summary>
    /// <param name="action">The action that caused the event.
    /// <param name="changedItems">The items affected by the change.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems)
    {
      if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
              && (action != NotifyCollectionChangedAction.Reset))
        throw new ArgumentException("SR.Get(SRID.MustBeResetAddOrRemoveActionForCtor)", "action");

      if (action == NotifyCollectionChangedAction.Reset)
      {
        if (changedItems != null)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresNullItem)", "action");

        InitializeAdd(action, null, -1);
      }
      else
      {
        if (changedItems == null)
          throw new ArgumentNullException("changedItems");

        InitializeAddOrRemove(action, changedItems, -1);
      }
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item change (or a reset).
    /// </summary>
    /// <param name="action">The action that caused the event.
    /// <param name="changedItems">The items affected by the change.
    /// <param name="startingIndex">The index where the change occurred.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
    {
      if ((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)
              && (action != NotifyCollectionChangedAction.Reset))
        throw new ArgumentException("SR.Get(SRID.MustBeResetAddOrRemoveActionForCtor)", "action");

      if (action == NotifyCollectionChangedAction.Reset)
      {
        if (changedItems != null)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresNullItem)", "action");
        if (startingIndex != -1)
          throw new ArgumentException("SR.Get(SRID.ResetActionRequiresIndexMinus1)", "action");

        InitializeAdd(action, null, -1);
      }
      else
      {
        if (changedItems == null)
          throw new ArgumentNullException("changedItems");
        if (startingIndex < -1)
          throw new ArgumentException("SR.Get(SRID.IndexCannotBeNegative)", "startingIndex");

        InitializeAddOrRemove(action, changedItems, startingIndex);
      }
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
    /// </summary>
    /// <param name="action">Can only be a Replace action.
    /// <param name="newItem">The new item replacing the original item.
    /// <param name="oldItem">The original item that is replaced.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem)
    {
      if (action != NotifyCollectionChangedAction.Replace)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Replace)", "action");

      InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Replace event.
    /// </summary>
    /// <param name="action">Can only be a Replace action.
    /// <param name="newItem">The new item replacing the original item.
    /// <param name="oldItem">The original item that is replaced.
    /// <param name="index">The index of the item being replaced.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
    {
      if (action != NotifyCollectionChangedAction.Replace)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Replace)", "action");

      InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
    /// </summary>
    /// <param name="action">Can only be a Replace action.
    /// <param name="newItems">The new items replacing the original items.
    /// <param name="oldItems">The original items that are replaced.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems)
    {
      if (action != NotifyCollectionChangedAction.Replace)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Replace)", "action");
      if (newItems == null)
        throw new ArgumentNullException("newItems");
      if (oldItems == null)
        throw new ArgumentNullException("oldItems");

      InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Replace event.
    /// </summary>
    /// <param name="action">Can only be a Replace action.
    /// <param name="newItems">The new items replacing the original items.
    /// <param name="oldItems">The original items that are replaced.
    /// <param name="startingIndex">The starting index of the items being replaced.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
    {
      if (action != NotifyCollectionChangedAction.Replace)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Replace)", "action");
      if (newItems == null)
        throw new ArgumentNullException("newItems");
      if (oldItems == null)
        throw new ArgumentNullException("oldItems");

      InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a one-item Move event.
    /// </summary>
    /// <param name="action">Can only be a Move action.
    /// <param name="changedItem">The item affected by the change.
    /// <param name="index">The new index for the changed item.
    /// <param name="oldIndex">The old index for the changed item.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
    {
      if (action != NotifyCollectionChangedAction.Move)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Move)", "action");
      if (index < 0)
        throw new ArgumentException("SR.Get(SRID.IndexCannotBeNegative)", "index");

      object[] changedItems = new object[] { changedItem };
      InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
    }

    /// <summary>
    /// Construct a NotifyCollectionChangedEventArgs that describes a multi-item Move event.
    /// </summary>
    /// <param name="action">The action that caused the event.
    /// <param name="changedItems">The items affected by the change.
    /// <param name="index">The new index for the changed items.
    /// <param name="oldIndex">The old index for the changed items.
    public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
    {
      if (action != NotifyCollectionChangedAction.Move)
        throw new ArgumentException("SR.Get(SRID.WrongActionForCtor, NotifyCollectionChangedAction.Move)", "action");
      if (index < 0)
        throw new ArgumentException("SR.Get(SRID.IndexCannotBeNegative)", "index");

      InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
    }

    private void InitializeAddOrRemove(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
    {
      if (action == NotifyCollectionChangedAction.Add)
        InitializeAdd(action, changedItems, startingIndex);
      else if (action == NotifyCollectionChangedAction.Remove)
        InitializeRemove(action, changedItems, startingIndex);
      else
      {
        // Invariant.Assert(false, "Unsupported action: {0}", action.ToString());
      }
    }

    private void InitializeAdd(NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
    {
      _action = action;
      _newItems = (newItems == null) ? null : newItems; // ArrayList.ReadOnly(newItems);
      _newStartingIndex = newStartingIndex;
    }

    private void InitializeRemove(NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
    {
      _action = action;
      _oldItems = (oldItems == null) ? null : oldItems; // ArrayList.ReadOnly(oldItems);
      _oldStartingIndex = oldStartingIndex;
    }

    private void InitializeMoveOrReplace(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
    {
      InitializeAdd(action, newItems, startingIndex);
      InitializeRemove(action, oldItems, oldStartingIndex);
    }

    //------------------------------------------------------
    //
    //  Public Properties
    //
    //-----------------------------------------------------

    /// <summary>
    /// The action that caused the event.
    /// </summary>
    public NotifyCollectionChangedAction Action
    {
      get { return _action; }
    }

    /// <summary>
    /// The items affected by the change.
    /// </summary>
    public IList NewItems
    {
      get { return _newItems; }
    }

    /// <summary>
    /// The old items affected by the change (for Replace events).
    /// </summary>
    public IList OldItems
    {
      get { return _oldItems; }
    }

    /// <summary>
    /// The index where the change occurred.
    /// </summary>
    public int NewStartingIndex
    {
      get { return _newStartingIndex; }
    }

    /// <summary>
    /// The old index where the change occurred (for Move events).
    /// </summary>
    public int OldStartingIndex
    {
      get { return _oldStartingIndex; }
    }

    //------------------------------------------------------
    //
    //  Private Fields
    //
    //------------------------------------------------------

    private NotifyCollectionChangedAction _action;
    private IList _newItems, _oldItems;
    private int _newStartingIndex = -1;
    private int _oldStartingIndex = -1;
  }

  /// <summary>
  ///     The delegate to use for handlers that receive the CollectionChanged event.
  /// </summary>
  public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e);

  public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
  {
    //-----------------------------------------------------
    //
    //  Constructors
    //
    //-----------------------------------------------------

    #region Constructors
    /// <summary>
    /// Initializes a new instance of ObservableCollection that is empty and has default initial capacity.
    /// </summary>
    public ObservableCollection() : base() { }

    /// <summary>
    /// Initializes a new instance of the ObservableCollection class
    /// that contains elements copied from the specified list
    /// </summary>
    /// <param name="list">The list whose elements are copied to the new list.
    /// <remarks>
    /// The elements are copied onto the ObservableCollection in the
    /// same order they are read by the enumerator of the list.
    /// </remarks>
    /// <exception cref="ArgumentNullException"> list is a null reference </exception>
    public ObservableCollection(List<T> list)
      : base((list != null) ? new List<T>(list.Count) : list)
    {
      // Workaround for VSWhidbey bug 562681 (tracked by Windows bug 1369339).
      // We should be able to simply call the base(list) ctor.  But Collection<T>
      // doesn't copy the list (contrary to the documentation) - it uses the
      // list directly as its storage.  So we do the copying here.
      //
      CopyFrom(list);
    }

    /// <summary>
    /// Initializes a new instance of the ObservableCollection class that contains
    /// elements copied from the specified collection and has sufficient capacity
    /// to accommodate the number of elements copied.
    /// </summary>
    /// <param name="collection">The collection whose elements are copied to the new list.
    /// <remarks>
    /// The elements are copied onto the ObservableCollection in the
    /// same order they are read by the enumerator of the collection.
    /// </remarks>
    /// <exception cref="ArgumentNullException"> collection is a null reference </exception>
    public ObservableCollection(IEnumerable<T> collection)
    {
      if (collection == null)
        throw new ArgumentNullException("collection");

      CopyFrom(collection);
    }

    private void CopyFrom(IEnumerable<T> collection)
    {
      IList<T> items = Items;
      if (collection != null && items != null)
      {
        using (IEnumerator<T> enumerator = collection.GetEnumerator())
        {
          while (enumerator.MoveNext())
          {
            items.Add(enumerator.Current);
          }
        }
      }
    }

    #endregion Constructors


    //------------------------------------------------------
    //
    //  Public Methods
    //
    //-----------------------------------------------------

    #region Public Methods

    /// <summary>
    /// Move item at oldIndex to newIndex.
    /// </summary>
    public void Move(int oldIndex, int newIndex)
    {
      MoveItem(oldIndex, newIndex);
    }

    #endregion Public Methods


    //------------------------------------------------------
    //
    //  Public Events
    //
    //------------------------------------------------------

    #region Public Events

    //-----------------------------------------------------
    #region INotifyPropertyChanged implementation

    /// <summary>
    /// PropertyChanged event (per <see cref="INotifyPropertyChanged">).
    /// </see></summary>
    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
      add
      {
        PropertyChanged += value;
      }
      remove
      {
        PropertyChanged -= value;
      }
    }
    #endregion INotifyPropertyChanged implementation


    //------------------------------------------------------
    /// <summary>
    /// Occurs when the collection changes, either by adding or removing an item.
    /// </summary>
    /// <remarks>
    /// see <seealso cref="INotifyCollectionChanged">
    /// </seealso></remarks>
    // [field: NonSerializedAttribute()]
    public virtual event NotifyCollectionChangedEventHandler CollectionChanged;

    #endregion Public Events


    //-----------------------------------------------------
    //
    //  Protected Methods
    //
    //-----------------------------------------------------

    #region Protected Methods

    /// <summary>
    /// Called by base class Collection<T> when the list is being cleared;
    /// raises a CollectionChanged event to any listeners.
    /// </summary>
    protected override void ClearItems()
    {
      CheckReentrancy();
      base.ClearItems();
      OnPropertyChanged(CountString);
      OnPropertyChanged(IndexerName);
      OnCollectionReset();
    }

    /// <summary>
    /// Called by base class Collection<T> when an item is removed from list;
    /// raises a CollectionChanged event to any listeners.
    /// </summary>
    protected override void RemoveItem(int index)
    {
      CheckReentrancy();
      T removedItem = this[index];

      base.RemoveItem(index);

      OnPropertyChanged(CountString);
      OnPropertyChanged(IndexerName);
      OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, index);
    }

    /// <summary>
    /// Called by base class Collection<T> when an item is added to list;
    /// raises a CollectionChanged event to any listeners.
    /// </summary>
    protected override void InsertItem(int index, T item)
    {
      CheckReentrancy();
      base.InsertItem(index, item);

      OnPropertyChanged(CountString);
      OnPropertyChanged(IndexerName);
      OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
    }

    /// <summary>
    /// Called by base class Collection<T> when an item is set in list;
    /// raises a CollectionChanged event to any listeners.
    /// </summary>
    protected override void SetItem(int index, T item)
    {
      CheckReentrancy();
      T originalItem = this[index];
      base.SetItem(index, item);

      OnPropertyChanged(IndexerName);
      OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, item, index);
    }

    /// <summary>
    /// Called by base class ObservableCollection<T> when an item is to be moved within the list;
    /// raises a CollectionChanged event to any listeners.
    /// </summary>
    protected virtual void MoveItem(int oldIndex, int newIndex)
    {
      CheckReentrancy();

      T removedItem = this[oldIndex];

      base.RemoveItem(oldIndex);
      base.InsertItem(newIndex, removedItem);

      OnPropertyChanged(IndexerName);
      OnCollectionChanged(NotifyCollectionChangedAction.Move, removedItem, newIndex, oldIndex);
    }


    /// <summary>
    /// Raises a PropertyChanged event (per <see cref="INotifyPropertyChanged">).
    /// </see></summary>
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, e);
      }
    }

    /// <summary>
    /// PropertyChanged event (per <see cref="INotifyPropertyChanged">).
    /// </see></summary>
    // [field: NonSerializedAttribute()]
    protected virtual event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raise CollectionChanged event to any listeners.
    /// Properties/methods modifying this ObservableCollection will raise
    /// a collection changed event through this virtual method.
    /// </summary>
    /// <remarks>
    /// When overriding this method, either call its base implementation
    /// or call <see cref="BlockReentrancy"> to guard against reentrant collection changes.
    /// </see></remarks>
    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
      if (CollectionChanged != null)
      {
        using (BlockReentrancy())
        {
          CollectionChanged(this, e);
        }
      }
    }

    /// <summary>
    /// Disallow reentrant attempts to change this collection. E.g. a event handler
    /// of the CollectionChanged event is not allowed to make changes to this collection.
    /// </summary>
    /// <remarks>
    /// typical usage is to wrap e.g. a OnCollectionChanged call with a using() scope:
    /// <code>
    ///         using (BlockReentrancy())
    ///         {
    ///             CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, item, index));
    ///         }
    /// </code>
    /// </remarks>
    protected IDisposable BlockReentrancy()
    {
      _monitor.Enter();
      return _monitor;
    }

    /// <summary> Check and assert for reentrant attempts to change this collection. </summary>
    /// <exception cref="InvalidOperationException"> raised when changing the collection
    /// while another collection change is still being notified to other listeners </exception>
    protected void CheckReentrancy()
    {
      if (_monitor.Busy)
      {
        // we can allow changes if there's only one listener - the problem
        // only arises if reentrant changes make the original event args
        // invalid for later listeners.  This keeps existing code working
        // (e.g. Selector.SelectedItems).
        if ((CollectionChanged != null) && (CollectionChanged.GetInvocationList().Length > 1))
          throw new InvalidOperationException("SR.Get(SRID.ObservableCollectionReentrancyNotAllowed)");
      }
    }

    #endregion Protected Methods


    //-----------------------------------------------------
    //
    //  Private Methods
    //
    //------------------------------------------------------

    #region Private Methods
    /// <summary>
    /// Helper to raise a PropertyChanged event  />).
    /// </summary>
    private void OnPropertyChanged(string propertyName)
    {
      OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    /// <summary>
    /// Helper to raise CollectionChanged event to any listeners
    /// </summary>
    private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
    {
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
    }

    /// <summary>
    /// Helper to raise CollectionChanged event to any listeners
    /// </summary>
    private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex)
    {
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
    }

    /// <summary>
    /// Helper to raise CollectionChanged event to any listeners
    /// </summary>
    private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
    {
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
    }

    /// <summary>
    /// Helper to raise CollectionChanged event with action == Reset to any listeners
    /// </summary>
    private void OnCollectionReset()
    {
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }
    #endregion Private Methods

    //-----------------------------------------------------
    //
    //  Private Types
    //
    //------------------------------------------------------

    #region Private Types

    // this class helps prevent reentrant calls
    // [Serializable()]
    private class SimpleMonitor : IDisposable
    {
      public void Enter()
      {
        ++_busyCount;
      }

      public void Dispose()
      {
        --_busyCount;
      }

      public bool Busy { get { return _busyCount > 0; } }

      int _busyCount;
    }

    #endregion Private Types

    //------------------------------------------------------
    //
    //  Private Fields
    //
    //-----------------------------------------------------

    #region Private Fields

    private const string CountString = "Count";

    // This must agree with Binding.IndexerName.  It is declared separately
    // here so as to avoid a dependency on PresentationFramework.dll.
    private const string IndexerName = "Item[]";

    private SimpleMonitor _monitor = new SimpleMonitor();

    #endregion Private Fields
  }


}
  

